//! parser trait 和 一些组合子(变化一个 parse)
pub type ParserResult<'a, Out> = Result<(&'a str, Out), &'a str>;

pub struct BoxedParser<'a, T>(Box<dyn Parser<'a, T> + 'a>);

impl<'a, Output> BoxedParser<'a, Output> {
    fn new<P>(parser: P) -> Self
    where
        P: Parser<'a, Output> + 'a,
    {
        BoxedParser(Box::new(parser))
    }
}

impl<'a, Output> Parser<'a, Output> for BoxedParser<'a, Output> {
    fn parse(&self, input: &'a str) -> ParserResult<'a, Output> {
        self.0.parse(input)
    }
}

pub trait Parser<'a, T> {
    fn parse(&self, input: &'a str) -> ParserResult<'a, T>;

    fn map<F, NewOutput>(self, map_fn: F) -> BoxedParser<'a, NewOutput>
    where
        Self: Sized + 'a,
        T: 'a,
        NewOutput: 'a,
        F: Fn(T) -> NewOutput + 'a,
    {
        BoxedParser::new(map(self, map_fn))
    }

    /// 接收一个函数 map， map 返回一个 ParserResult
    fn and_then<F, NextP, NewOutput>(self, map_fn: F) -> BoxedParser<'a, NewOutput>
    where
        Self: Sized + 'a,
        T: 'a,
        NewOutput: 'a,
        NextP: Parser<'a, NewOutput>,
        F: Fn(T) -> NextP + 'a,
    {
        BoxedParser::new(move |input| {
            self.parse(input)
                .and_then(|(next, result)| map_fn(result).parse(next))
        })
    }

    fn pipe<P, K>(self, parser: P) -> BoxedParser<'a, K>
    where
        Self: Sized + 'a,
        P: Parser<'a, K> + 'a,
        K: 'a,
        T: 'a,
    {
        BoxedParser::new(right(self, parser))
    }

    /// 解析但是忽略返回值
    fn ignore<P, K>(self, parser: P) -> BoxedParser<'a, T>
    where
        Self: Sized + 'a,
        P: Parser<'a, K> + 'a,
        K: 'a,
        T: 'a,
    {
        BoxedParser::new(left(self, parser))
    }

    /// 顺序测试，返回第一个成功的
    fn or<P>(self, parser: P) -> BoxedParser<'a, T>
    where
        Self: Sized + 'a,
        P: Parser<'a, T> + 'a,
        T: 'a,
    {
        BoxedParser::new(either(self, parser))
    }

    fn pred<F>(self, pred_fn: F) -> BoxedParser<'a, T>
    where
        Self: Sized + 'a,
        T: 'a,
        F: Fn(&T) -> bool + 'a,
    {
        BoxedParser::new(pred(self, pred_fn))
    }
}

/// 组合两个 parser
pub fn pair<'a, T, K>(
    parser1: impl Parser<'a, T>,
    parser2: impl Parser<'a, K>,
) -> impl Fn(&'a str) -> ParserResult<'a, (T, K)> {
    move |input: &'a str| {
        parser1.parse(input).and_then(|(next_input, res1)| {
            parser2
                .parse(next_input)
                .map(|(rest_input, res2)| (rest_input, (res1, res2)))
        })
    }
}

/// 将 返回值的 Ok(res) 的 res 变形
pub fn map<'a, A, B, P, Fmap>(origin: P, map_fn: Fmap) -> impl Parser<'a, B>
where
    P: Parser<'a, A>,
    Fmap: Fn(A) -> B,
{
    move |input| origin.parse(input).map(|(next, res)| (next, map_fn(res)))
}

/// equal to |a, b| map(pair(a, b), |(_left, right)| right)
/// 组合两个 parser，返回值取后一个
pub fn right<'a, A, B, P1, P2>(parser1: P1, parser2: P2) -> impl Parser<'a, B>
where
    P1: Parser<'a, A>,
    P2: Parser<'a, B>,
{
    move |input: &'a str| {
        parser1.parse(input).and_then(|(next_input, _)| {
            parser2
                .parse(next_input)
                .map(|(rest_input, result)| (rest_input, result))
        })
    }
}

pub fn left<'a, A, B, P1, P2>(parser1: P1, parser2: P2) -> impl Parser<'a, A>
where
    P1: Parser<'a, A>,
    P2: Parser<'a, B>,
{
    map(pair(parser1, parser2), |(left, _right)| left)
}

// 毫无疑问，可以简单的通过 zero_or_more 定义 one_or_more, 只需要
// pred(zero_or_more, |vec| vec.len() != 0), 但是这样定义性能会差一点
/// 将同一个 parser 应用多次, 如果一次没应用就会返回 Err
pub fn one_or_more<'a, R, P>(parser: P) -> impl Parser<'a, Vec<R>>
where
    P: Parser<'a, R>,
{
    move |input| -> ParserResult<'a, Vec<R>> {
        let (output, first) = parser.parse(input)?;
        let mut results = vec![first];

        let mut output = output;
        while let Ok((next_input, res)) = parser.parse(output) {
            output = next_input;
            results.push(res);
        }

        Ok((output, results))
    }
}

/// 将同一个 parser 应用多次, 允许为 0 次
pub fn zero_or_more<'a, R, P>(parser: P) -> impl Parser<'a, Vec<R>>
where
    P: Parser<'a, R>,
{
    move |mut input| -> ParserResult<'a, Vec<R>> {
        let mut results = vec![];

        while let Ok((next_input, res)) = parser.parse(input) {
            input = next_input;
            results.push(res);
        }

        Ok((input, results))
    }
}

/// 判断一个 parse 的返回值是否满足一定条件
pub fn pred<'a, R, P, Test>(parser: P, test: Test) -> impl Parser<'a, R>
where
    P: Parser<'a, R>,
    Test: Fn(&R) -> bool,
{
    move |input| {
        parser.parse(input).and_then(|(next_input, res)| {
            if test(&res) {
                Ok((next_input, res))
            } else {
                Err(input)
            }
        })
    }
}

pub fn either<'a, P1, P2, R>(parser1: P1, parser2: P2) -> impl Parser<'a, R>
where
    P1: Parser<'a, R>,
    P2: Parser<'a, R>,
{
    move |input| match parser1.parse(input) {
        ok @ Ok(_) => ok,
        Err(_) => parser2.parse(input),
    }
}

impl<'a, T, F> Parser<'a, T> for F
where
    F: Fn(&'a str) -> ParserResult<T>,
{
    fn parse(&self, input: &'a str) -> ParserResult<'a, T> {
        self(input)
    }
}
